/**
 * @author bruno perry
 * @since 16-11-2009
 * 
 * This is an excerpt from the MICRO-GZM project (code.google.com/p/micro-gzm/)
 */
 
import math3D.Matrix3D;
 
class math3D.Vector3D {
	
	public var x:Number;
	public var y:Number;
	public var z:Number;
	public var type:String;
	
	/*************************************
	 * CONSTRUCTOR
	 *************************************/
	public function Vector3D(valX:Number,valY:Number,valZ:Number, t:String) {
		
		x = valX;
		y = valY;
		z = valZ;
		
		type = t; 
	}
	/*************************************
	 * OPERATORS
	 *************************************/
	/**
	 * Adds a vector
	 * @param v1 vector to add
	 * @return new Vector3D ( this + v1 = new v )
	 */
	public function add(v1:Vector3D):Vector3D {
		return new Vector3D(x+v1.x,y+v1.y,z+v1.z);
		}	
	/**
	 * Subtracts a vector
	 * @param v1 vector to add
	 * @return new Vector3D ( this - v1 = new v )
	 */
	public function subtract(v1:Vector3D):Vector3D {
		return new Vector3D(x-v1.x,y-v1.y,z-v1.z);
		}
	/**
	 * Equals a vector
	 * @param v1 vector to equal
	 * @return new Vector3D ( this = v1 = new v )
	 */
	public function equals(v1:Vector3D):Vector3D {
		return new Vector3D(x=v1.x,y=v1.y,z=v1.z);
		}
	/**
	 * Multiplies by a number
	 * @param n number to multiply
	 * @return new Vector3D ( this * n = new v )
	 */
	public function multiply(n:Number):Vector3D {
		return new Vector3D(x*n,y*n,z*n);
	}
	/**
	 * increase by a vector
	 * @param v1 vector to increase
	 */
	public function plusEquals(v1:Vector3D):Void {
		
		x += v1.x;
		y += v1.y;
		z += v1.z;
	}
	/*************************************
	 * VECTOR MATH
	 *************************************/
	/**
	 * Simmetry by a vector
	 */
	public function Negate():Void {
		x = -x;
		y = -y;
		z = -z;
	}
	/**
	 * Determines the dot product by another vector
	 * @param v vector to operate
	 * @returns the dot product
	 */
	public function Dot(v:Vector3D):Number {
		return x*v.x+y*v.y+z*v.z;
	}
	/**
	 * Determines the magnitude of the vector
	 * @return magnitude value
	 */
	public function Magnitude():Number {
		return Math.sqrt(x*x+y*y+z*z);
	}
	/**
	 * Normalizes the vector
	 */
	public function SelfNormalize():Void {
		
		var len:Number = Magnitude();
		
		if(len<=0.00001)
		   len=1;
		
		len = 1/len;
		
		x*=len;
		y*=len;
		z*=len;
	}
	/**
	 * Normalizes vector by 3 others
	 * @param p1 vector to normalize
	 * @param p2 vector to normalize
	 * @param p3 vector to normalize
	 */
	public function Normalize(p1:Vector3D,p2:Vector3D,p3:Vector3D):Void {
		var e1:Vector3D = p1.subtract(p2);
		var e2:Vector3D = p2.subtract(p3);
		
		e1.SelfNormalize();
		e2.SelfNormalize();
		
		this.equals(e1.CrossProduct(e2));
		SelfNormalize();
	}
	/**
	 * Determines the cross product by another vertice
	 * @param v1 vector to cross
	 * @return crossed vector
	 */
	public function CrossProduct(v1:Vector3D):Vector3D {
		
		return new Vector3D(y*v1.z - z*v1.y,
							z*v1.x - x*v1.z,
							x*v1.y - y*v1.x);
	}
}